//
// Copyright (c) 2009 All Right Reserved
//
// vl
//
// 2009-01-01
// Contains ...
using System;
using System.Diagnostics.Contracts;
using System.Text;
using System.Xml.Serialization;
namespace LargoCommon.Music
{
/// Melodic interval.
/// MelodicInterval represents one interval, i.e. relation of two pitches.
/// Includes characteristics like minimal track Value or easy sing Value used for
/// optimization of melodies.
/// [Serializable]
[XmlRoot]
public sealed class MelodicInterval : MusicalInterval
{
#region Fields
///
/// Musical pitch1.
///
private readonly MusicalPitch pitch1;
///
/// Musical pitch2.
///
private readonly MusicalPitch pitch2;
/// Interval musical properties.
private float? minTrack, easySing;
#endregion
#region Constructors
/// Initializes a new instance of the MelodicInterval class.
/// Harmonic system.
/// First musical pitch.
/// Second musical pitch.
public MelodicInterval(HarmonicSystem harmonicSystem, MusicalPitch givenPitch1, MusicalPitch givenPitch2)
: base(harmonicSystem, givenPitch1, givenPitch2) {
Contract.Requires(harmonicSystem != null);
this.pitch1 = givenPitch1;
this.pitch2 = givenPitch2;
this.minTrack = null;
this.easySing = null;
}
/// Initializes a new instance of the MelodicInterval class. Serializable.
public MelodicInterval() {
}
/// Initializes a new instance of the MelodicInterval class.
/// Harmonic system.
/// Fist element of system.
/// Second element of system.
public MelodicInterval(HarmonicSystem harmonicSystem, byte elementFrom, byte elementTo)
: base(harmonicSystem, elementFrom, elementTo) {
Contract.Requires(harmonicSystem != null);
}
/// Initializes a new instance of the MelodicInterval class.
/// Harmonic system.
/// First melodic tone.
/// Second melodic tone.
public MelodicInterval(HarmonicSystem harmonicSystem, MusicalTone tone1, MusicalTone tone2)
: base(harmonicSystem, tone1, tone2) {
Contract.Requires(harmonicSystem != null);
Contract.Requires(tone1 != null);
Contract.Requires(tone2 != null);
}
#endregion
#region Properties
/// Gets the first pitch of the interval.
/// Property description.
public MusicalPitch Pitch1 {
get {
Contract.Ensures(Contract.Result() != null);
if (this.pitch1 == null) {
throw new InvalidOperationException("Pitch is null.");
}
return this.pitch1;
}
}
/// Gets the second pitch of the interval.
/// Property description.
public MusicalPitch Pitch2 {
get {
Contract.Ensures(Contract.Result() != null);
if (this.pitch2 == null) {
throw new InvalidOperationException("Pitch is null.");
}
return this.pitch2;
}
}
/// Gets the easy-sing value.
/// Evaluates how easy it is to sing given interval.
public float EasySing {
get {
if (this.easySing != null) {
return (float)this.easySing;
}
var harmonicSystem = this.Pitch2.HarmonicSystem;
//// int sysLength = this.Pitch1.DistanceFrom(this.Pitch2);
var frmLength = this.Pitch1.FormalDistanceFrom(this.Pitch2);
this.easySing = frmLength < harmonicSystem.Median ? 1.0f : -1.0f;
//// frmLength == 0 || (sysLength < harmonicSystem.Order && Math.Abs(FormalContinuity) > DefaultValue.Fifty)
//// || (sysLength < harmonicSystem.Order / 2 && FormalImpulse > DefaultValue.Fifty) ? 1.0f : -1.0f;
return (float)this.easySing;
}
}
/// Gets the minimum-track value.
/// Is higher for smaller changes in the musical pitch..
public float MinimumMotion {
//// float impulseValue = (fDist == 0) ? -1 : r;
get {
if (this.minTrack != null) {
return (float)this.minTrack;
}
var harmonicSystem = this.Pitch2.HarmonicSystem;
float distance = this.Pitch2.DistanceFrom(this.Pitch1);
var r = distance / harmonicSystem.Order; //// harmonicSystem.Order != 0 ? distance / harmonicSystem.Order : 0;
this.minTrack = r;
return (float)this.minTrack;
}
}
#endregion
#region String representation
/// String representation - not used, so marked as static.
/// Returns value.
public override string ToString() {
var s = new StringBuilder();
s.Append(this.Pitch1);
s.Append(this.Pitch2);
return s.ToString();
}
#endregion
}
}